package com.psdi.element;

import com.psdi.Main;
import com.psdi.controller.Input;
import com.psdi.controller.MouseButton;
import com.psdi.manager.ElementManager;
import com.psdi.manager.GameLoader;
import com.psdi.manager.LevelSystem;
import com.psdi.physics.Collider;
import com.psdi.physics.CollisionSystem;
import com.psdi.window.GameJFrame;

import javax.swing.*;
import java.awt.*;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

/**
 * 玩家类，继承自ElementObject
 * 用于表示游戏中的玩家
 */
public class Player extends ElementObject implements Collider{
    private float hp=0;
    private float maxhp=4;
    private float atk=1;
    private float speed = 1f;
    private float animationTime = 0.1f;
    private final Map<Vector2D, List<ImageIcon>> images = GameLoader.iconMap;
    private Vector2D direction=Vector2D.UP; // 玩家当前方向
    private  Vector2D destination=Vector2D.ZERO;//玩家移动目的地与自身的向量
    private Vector2D moveVector = Vector2D.ZERO; // 玩家移动向量
    private boolean isAttacking = false; // 是否正在攻击
    private static float DEFAULT_ATTACK_COOLDOWN = 0.1f; // 默认攻击冷却时间
    private float attackCooldown = DEFAULT_ATTACK_COOLDOWN; // 攻击冷却时间
    private float autoAttackCooldown = 30*DEFAULT_ATTACK_COOLDOWN; //自动攻击冷却时间
    private int num=0;//换装顺序
    public Player(){}

    public ElementObject CreatPlayer(){
        this.image = images.get(direction).get(0);
        this.transform = new Transform(new Position((float) GameJFrame.GAME_HEIGHT /2, (float) GameJFrame.GAME_HEIGHT /2),new Rotation(),new Size(image.getIconWidth()/2, image.getIconHeight()/2));
        Input.setMousePosition(new Point((int) this.transform.position.x, (int) this.transform.position.y),3);
        this.tag=Tag.PLAYER;
        setHp(maxhp);
        CollisionSystem.INSTANCE.addElement(this);
        return this;
    }

    public float getSpeed() {
        return speed;
    }

    public void setSpeed(float speed) {
        this.speed = speed;
    }

    @Override
    public void show(Graphics g) {
        g.drawImage(this.getImage().getImage(), (int) transform.position.x, (int) transform.position.y, transform.size.width, transform.size.height, null);
    }

    @Override
    public void update() {
        // 更新玩家状态
        // 例如：处理碰撞检测、更新动画等
        // 这里可以添加更多的逻辑来处理玩家的行为
        move();
        updateImage();
        attack();
        shoot();
    }

    private void mouseMove(){
        if (-destination.y> destination.x  && destination.y <0) {
            direction = Vector2D.UP;
        }else if(destination.x > destination.y  && destination.x >0){
            direction = Vector2D.RIGHT;
        }  else if (destination.y< -destination.x  && destination.x < 0) {
            direction = Vector2D.LEFT;
        } else if (destination.x< destination.y  && destination.y >0) {
            direction = Vector2D.DOWN;
        }

    }
    Position des = null;//只记录一次鼠标坐标
    private void move() {
        if(Input.getMouseButton(MouseButton.RIGHT) ){
            des = Input.getRightmousePosition();
            destination = Vector2D.displacement(transform.position, des);
            mouseMove();
            num=0;
        }

        if(des!=null && Position.distance(des,transform.position) > speed - 0.5){
            transform.position.add(destination.normalize().scalarMultiply(speed));
            animationTime -= Main.DELTA_TIME;
            if(animationTime <=0){
                animationTime = .1f;
                num++;
            }
        }
    }

    @Override
    protected void updateImage() {
        num%=4;
        // 根据方向更新玩家的图像
        if(num!=0){
            setImage(images.get(direction).get(num));
            return;
        }
        setImage(images.get(direction).get(0));


    }
    private void attack() {
        // 这里可以添加攻击逻辑，例如发射子弹等
        isAttacking = Input.getMouseButton(MouseButton.LEFT);
    }
    
    private void shoot() {
        if (attackCooldown==0) {
            // 发射子弹的逻辑
            // 例如：创建一个Bullet对象并添加到游戏中
            creatBullet();
            // 重置攻击冷却时间
            attackCooldown = 12*DEFAULT_ATTACK_COOLDOWN; // 重置攻击冷却时间
        }
        if (isAttacking && autoAttackCooldown == 0) {
            GameLoader.LoadKnifeairflow(knifeString());
            autoAttackCooldown = 10*DEFAULT_ATTACK_COOLDOWN; // 重置攻击冷却时间
        }
        if (attackCooldown > 0) {
            attackCooldown -= Main.DELTA_TIME; // 减少冷却时间
            if (attackCooldown < 0) attackCooldown = 0; // 确保冷却时间不会小于0
        }
        if (autoAttackCooldown > 0) {
            autoAttackCooldown -= Main.DELTA_TIME; // 减少冷却时间
            if (autoAttackCooldown < 0) autoAttackCooldown = 0; // 确保冷却时间不会小于0
        }
    }
    public boolean checkCondition(){
        return !(hp <= 0);
    }
    public void creatBullet(){
        for (int i=0;i<=LevelSystem.getINSTANCE().getLevel();i++){
            Executors.newScheduledThreadPool(1).schedule(() -> {
                GameLoader.LoadBullet(bulletString());
            }, i*250, TimeUnit.MILLISECONDS); // 500ms间隔
        }
    }
    public String bulletString() {
        Position center = transform.center();
        Vector2D offset = new Vector2D(15, 15);
        center.add(offset.hadamard(direction));
        return "x: " + center.x +
                "; y: " + center.y +
                 "; direction: " + direction +
                    "; atk: " + atk;
    }

    public String knifeString() {
        Position position = transform.center();
        return "x: " + position.x +
                "; y: " + position.y +
                "; direction: " + direction +
                "; atk: " + atk;
    }

    @Override
    public Size colliderSize() {
        return transform.size;
    }

    @Override
    public Position colliderPosition() {
        return transform.position;
    }

    @Override
    public Tag colliderTag() {
        return tag;
    }

    @Override
    public Set<Tag> colliderFilterTag() {
        Set<Tag> tags = new HashSet<>();
        tags.add(Tag.MAP);
        tags.add(Tag.BULLET);
        return tags;
    }

    @Override
    public void onCollisionStay(ElementObject other) {
        if(other instanceof Prop){
            other.transform.position.add(direction.scalarMultiply(-15));
        }

    }

    public float getAtk() {
        return atk;
    }

    public void setAtk(float atk) {
        this.atk = atk;
    }

    public float getHp() {
        return hp;
    }

    public void setHp(float hp) {
        this.hp = hp;
    }

    public float getDefaultAttackCooldown() {
        return DEFAULT_ATTACK_COOLDOWN;
    }

    public void setDefaultAttackCooldown(float defaultAttackCooldown) {
        DEFAULT_ATTACK_COOLDOWN = defaultAttackCooldown;
    }

    public void setMaxhp(float maxhp) {
        this.maxhp = maxhp;
    }
    public float getMaxhp() {
        return this.maxhp;
    }
}
